Windows批处理:将日期格式化为变量

您所在的位置:网站首页 windows cmd获取时间 Windows批处理:将日期格式化为变量

Windows批处理:将日期格式化为变量

2024-07-12 19:05| 来源: 网络整理| 查看: 265

如何将当前日期以YYYY-MM-DD格式保存到Windows .bat文件中的某个变量中?

Unix shell模拟:

12today=`date +%F` echo $today 相关讨论 可能重复的Windows批处理脚本格式的日期和时间 robvanderwoude.com/datetime.php adarshr,这个问题的答案使用了一种非常可怕且容易出错的方式来处理它。 我建议不要使用它。 此链接有助于理解以下答案。ss64.com/nt/for_f.html 无论区域设置如何,都会在批处理文件中拆分%date%

您可以使用与区域设置无关的方式获取当前日期

1for /f"skip=1" %%x in ('wmic os get localdatetime') do if not defined MyDate set MyDate=%%x

然后,您可以使用子字符串提取单个部分:

1set today=%MyDate:~0,4%-%MyDate:~4,2%-%MyDate:~6,2%

另一种方法,即获得包含各个部分的变量,将是:

12for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr"="') do set %%x set today=%Year%-%Month%-%Day%

比摆弄子串更好,代价是污染你的变量命名空间。

如果您需要UTC而不是本地时间,则命令或多或少相同:

12for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr"="') do set %%x set today=%Year%-%Month%-%Day% 相关讨论 需要注意的一点是,如果在测试此命令时打开命令提示符,它将为您提供打开命令提示符(cmd.exe)的时间。因此,如果您打开一段时间的命令提示符并保持同一时间,请关闭然后重新打开命令提示符。如果您只是从Windows资源管理器运行批处理文件,这将不是一个问题。 @ user2023861看来即使我打开命令提示符,我总是在调用命令时得到正确的日期/时间,而不是在我打开命令提示符时。 请注意,如果多次运行上面的行,则不会为每次调用获取新日期,因为它会检查未定义的变量。这是必需的,因为for /f返回两行,后者是空行。您可以通过在其间使用set MyDate=来解决这个问题。我猜这就是user2023861偶然发现的事情。 哦,是的,我只是echo wmic输出,因此每次调用时总是一个新的日期/时间。如果不首先执行if not defined MyDate,我似乎无法将其放在MyDate变量中。 男人,这个词需要传播这个方法。具有与语言环境无关的时间戳使得解析更容易并使批处理文件更加健壮(尽管我认为稳健性并不是??人们对Windows批处理文件的期望......)。 @CharlesWood,至少我在自己的批处理文件中力求稳健,尽管这些天我经常使用PowerShell。 @Joey我知道这是旧的,但有没有办法在文件上执行此操作以获得类似格式的"修改日期"?谢谢。 将设置的变量:Year,Month,Day,Hour,Minute,Second,Quarter,WeekInMonth,DayOfWeek 天哪。我知道Windows批处理文件是原始的,但这只是可怕的。我发现自己正在考虑制作一个小批量文件来自动创建以当天命名的大胆记录会话,等等,但是看看如何做的选项,我决定等到我用Linux替换XP,希望在新年。 @Majenko:你也可以使用VBScript或PowerShell。在Windows上有很多东西可以编写脚本。 XP上的电源外壳?而且我宁愿吃自己的脚而不是涉猎VirusBasicScript。 for /f %%x in ('wmic path win32_localtime get /format:list ^| findstr"="') do set %%x set today=%Year%-%Month%-%Day%是无效答案:它返回一个月的数字和日期。如何在零月和日期字符串的情况下获得2位左边填充?

如果您希望在批处理文件中使用标准MS-DOS命令实现此目的,那么您可以使用:

123FOR /F"TOKENS=1 eol=/ DELIMS=/" %%A IN ('DATE/T') DO SET dd=%%A FOR /F"TOKENS=1,2 eol=/ DELIMS=/" %%A IN ('DATE/T') DO SET mm=%%B FOR /F"TOKENS=1,2,3 eol=/ DELIMS=/" %%A IN ('DATE/T') DO SET yyyy=%%C

我确信这可以进一步改进,但这会将日期分为3个变量,分别为Day(dd),Month(mm)和Year(yyyy)。然后,您可以根据需要在批处理脚本中使用它们。

12345SET todaysdate=%yyyy%%mm%%dd% echo %dd% echo %mm% echo %yyyy% echo %todaysdate%

虽然我理解这个问题已经接受了答案,但是许多人希望在不使用WMI控制台的情况下实现这一目标,所以我希望它能为这个问题增加一些价值。

相关讨论 我发现我需要在Windows 7机箱上略微改变它。令牌需要增加一个:... FOR / F"TOKENS = 2,3,4 eol = / DELIMS = /"...... 在Azure上的Win server 2012上也是如此

使用date / T在命令提示符下查找格式。

如果日期格式为"Thu 03/03/2016",请使用如下:

12set datestr=%date:~10,4%-%date:~7,2%-%date:~4,2% echo %datestr% 相关讨论 这是对问题最接近的答案。我只需要一个简单的单行程,而不是程序。 同意。这里的一些答案看起来几乎像"安装MS SQL Server,连接SQL客户端,并执行命令SELECT CONVERT(VARCHAR(16), GETDATE(), 112)"。 ISO-8601格式的日期时间是%date:~10,4%%date:~7,2%%date:~4,2%T%time:~0,2%%time:~3,2%%time:~6,2%

另外两种不依赖于时间设置的方法(均来自如何获取数据/时间与本地化无关)。而且两者都得到了一周的日子,而且没有一个需要管理员权限!:

MAKECAB - 将在每个Windows系统上工作(快速,但创建一个小的临时文件)(foxidrive脚本):

123456789101112@echo off pushd"%temp%" makecab /D RptFileName=~.rpt /D InfFileName=~.inf /f nul >nul for /f"tokens=3-7" %%a in ('find /i"makecab"^nul 2>&1|| copy /Y %windir%\System32\doskey.exe %windir%\System32\'.exe >nul '& echo current date: '& cscript /nologo /E:vbscript"%~f0" '& exit /b '0 = vbGeneralDate - Default. Returns date: mm/dd/yy and time if specified: hh:mm:ss PM/AM. '1 = vbLongDate - Returns date: weekday, monthname, year '2 = vbShortDate - Returns date: mm/dd/yy '3 = vbLongTime - Returns time: hh:mm:ss PM/AM '4 = vbShortTime - Return time: hh:mm WScript.echo  Replace(FormatDateTime(Date, 1),",","-")

PowerShell - 可以安装在每台具有.NET的计算机上 - 从Microsoft下载(v1,v2和v3(仅适用于Windows  7及以上版本))。默认安装在Windows  7 / Win2008及以上版本的所有内容中:

1C:\> powershell get-date -format"{dd-MMM-yyyy HH:mm}"

自编的jscript.net/batch(我从未见过没有.NET的Windows机器所以我认为这是一个非常便携的):

123456789101112131415161718192021222324252627282930313233343536373839@if (@X)==(@Y) @end /****** silent line that start jscript comment ****** @echo off :::::::::::::::::::::::::::::::::::: :::       Compile the script    :::: :::::::::::::::::::::::::::::::::::: setlocal if exist"%~n0.exe" goto :skip_compilation set"frm=%SystemRoot%\Microsoft.NET\Framework" :: searching the latest installed .net framework for /f"tokens=* delims=" %%v in ('dir /b /s /a:d /o:-n"%SystemRoot%\Microsoft.NET\Framework\v*"') do (     if exist"%%v\jsc.exe" (         rem :: the javascript.net compiler         set"jsc=%%~dpsnfxv\jsc.exe"         goto :break_loop     ) ) echo jsc.exe not found && exit /b 0 :break_loop call %jsc% /nologo /out:"%~n0.exe""%~dpsfnx0" :::::::::::::::::::::::::::::::::::: :::       End of compilation    :::: :::::::::::::::::::::::::::::::::::: :skip_compilation "%~n0.exe" exit /b 0 ****** End of JScript comment ******/ import System; import System.IO; var dt=DateTime.Now; Console.WriteLine(dt.ToString("yyyy-MM-dd hh:mm:ss"));

Logman这不能得到一周中的一年和一天。它相对较慢,也会创建一个临时文件,并基于logman放在其日志文件上的时间戳。将从Windows  XP及以上版本开始工作。它可能永远不会被任何人使用 - 包括我 - 但它还有一种方式......

12345678910111213141516171819202122@echo off setlocal del /q /f %temp%\timestampfile_* Logman.exe stop ts-CPU 1>nul 2>&1 Logman.exe delete ts-CPU 1>nul 2>&1 Logman.exe create counter ts-CPU  -sc 2 -v mmddhhmm -max 250 -c"\Processor(_Total)\%% Processor Time" -o %temp%\timestampfile_ >nul Logman.exe start ts-CPU 1>nul 2>&1 Logman.exe stop ts-CPU >nul 2>&1 Logman.exe delete ts-CPU >nul 2>&1 for /f"tokens=2 delims=_." %%t in  ('dir /b %temp%\timestampfile_*^&del /q/f %temp%\timestampfile_*') do set timestamp=%%t echo %timestamp% echo MM: %timestamp:~0,2% echo dd: %timestamp:~2,2% echo hh: %timestamp:~4,2% echo mm: %timestamp:~6,2% endlocal exit /b 0

有关Get-Date功能的更多信息。

我真的很喜欢Joey的方法,但我想我会稍微扩展一下。

在这种方法中,您可以多次运行代码,而不必担心旧的日期值"粘附",因为它已经定义。

每次运行此批处理文件时,它都将输出ISO 8601兼容的组合日期和时间表示。

1234FOR /F"skip=1" %%D IN ('WMIC OS GET LocalDateTime') DO (SET LIDATE=%%D & GOTO :GOT_LIDATE) :GOT_LIDATE SET DATETIME=%LIDATE:~0,4%-%LIDATE:~4,2%-%LIDATE:~6,2%T%LIDATE:~8,2%:%LIDATE:~10,2%:%LIDATE:~12,2% ECHO %DATETIME%

在此版本中,您必须小心不要将相同的代码复制/粘贴到文件中的多个位置,因为这会导致重复的标签。您可以为每个副本设置单独的标签,或者只是将此代码放入其自己的批处理文件中,并在必要时从源文件中调用它。

只需使用%date%变量:

1echo %date% 相关讨论 这将以当前配置的短日期格式返回日期。这很少是ISO-8601。 @Joey同意 - 我在这里是因为这还不够好依靠。

根据@ProVi的回答,只需更改以适应您需要的格式

1echo %DATE:~10,4%-%DATE:~7,2%-%DATE:~4,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2%

将返回

12yyyy-MM-dd hh:mm:ss 2015-09-15 18:36:11

编辑 根据@Jeb评论,谁是正确的,上述时间格式只有在你的DATE / T命令返回时才有效

12ddd dd/mm/yyyy Thu 17/09/2015

可以很容易地编辑以适合您的语言环境,但是,通过使用相关%DATE%环境变量返回的字符串中每个字符的索引,您可以提取所需字符串的部分。

例如。使用%DATE~10,4%将扩展DATE环境变量,然后仅使用从扩展结果的第11个(偏移10)字符开始的4个字符

例如,如果使用美国风格的日期,则以下适用

12345ddd mm/dd/yyyy Thu 09/17/2015 echo %DATE:~10,4%-%DATE:~4,2%-%DATE:~7,2% %TIME:~0,2%:%TIME:~3,2%:%TIME:~6,2% 2015-09-17 18:36:11 相关讨论 这只是某些人的解决方案,因为这只适用于世界上的某些地方,具体取决于您的日期/时间格式设置

我通过这样做将环境变量设置为所需的数字格式的值:

1FOR /F"tokens=1,2,3,4 delims=/" %a IN ('echo %date%') DO set DateRun=%d-%b-%c

如果您安装了Python,则可以执行此操作

1python -c"import datetime;print(datetime.date.today().strftime('%Y-%m-%d'))"

您可以轻松地根据需要调整格式字符串。

相关讨论 以什么方式说"使用python"这个问题的答案? 与使用MAKECAB,ROBOCOPY,VBSCRIPT,POWERSHELL Logman和其他建议一样,您可以在命令行上调用?

检查一下......

12345678for /f"tokens=2 delims==" %%a in ('wmic OS Get localdatetime /value') do set"dt=%%a" set"YY=%dt:~2,2%" & set"YYYY=%dt:~0,4%" & set"MM=%dt:~4,2%" & set"DD=%dt:~6,2%" set"HH=%dt:~8,2%" & set"Min=%dt:~10,2%" & set"Sec=%dt:~12,2%" & set"MS=%dt:~15,3%" set"datestamp=%YYYY%%MM%%DD%" & set"timestamp=%HH%%Min%%Sec%" & set"fullstamp=%YYYY%-%MM%-%DD%_%HH%-%Min%-%Sec%-%MS%" echo datestamp:"%datestamp%" echo timestamp:"%timestamp%" echo fullstamp:"%fullstamp%" pause

可以使用PowerShell并使用循环将其输出重定向到环境变量。

从命令行(cmd):

1234for /f"tokens=*" %a in ('powershell get-date -format"{yyyy-mm-dd+HH:mm}"') do set td=%a echo %td% 2016-25-02+17:25

在批处理文件中,您可以将%a转义为%%a:

1for /f"tokens=*" %%a in ('powershell get-date -format"{yyyy-mm-dd+HH:mm}"') do set td=%%a 相关讨论 掩码应该像这样FOR /F"tokens=*" %%a IN ('powershell get-date -format"{yyyy\-MM\-dd\THH\:mm\:ss}"') DO SET date=%%a所以使用上部MM表示月份和反斜杠来逃避文字字符。

由于日期和时间格式是特定于位置的信息,从%date%和%time%变量中检索它们将需要额外的努力来解析格式转换的字符串。一个好主意是使用一些API来检索数据结构并根据需要进行解析。 WMIC是一个不错的选择。下面的例子使用Win32_LocalTime。您还可以使用Win32_CurrentTime或Win32_UTCTime。

123456789101112@echo off   SETLOCAL ENABLEDELAYEDEXPANSION   for /f %%x in ('wmic path Win32_LocalTime get /format:list ^| findstr"="') do set %%x   set yyyy=0000%Year%   set mmmm=0000%Month%   set dd=00%Day%   set hh=00%Hour%   set mm=00%Minute%   set ss=00%Second%   set ts=!yyyy:~-4!-!mmmm:~-2!-!dd:~-2!_!hh:~-2!:!mm:~-2!:!ss:~-2!   echo %ts%   ENDLOCAL

结果: 2018-04-25_10:03:11

这是Joey的答案的延伸,包括时间和填充0的部分。

例如,结果将是2019-06-01_17-25-36。 另请注意,这是UTC时间。

1234567891011121314  for /f %%x in ('wmic path win32_utctime get /format:list ^| findstr"="') do set %%x   set Month=0%Month%   set Month=%Month:~-2%   set Day=0%Day%   set Day=%Day:~-2%   set Hour=0%Hour%   set Hour=%Hour:~-2%   set Minute=0%Minute%   set Minute=%Minute:~-2%   set Second=0%Second%   set Second=%Second:~-2%   set TimeStamp=%Year%-%Month%-%Day%_%Hour%-%Minute%-%Second% 1echo %DATE:~10,4%%DATE:~7,2%%DATE:~4,2% 相关讨论 输出像这样20160711

如果您不介意一次性投资10到30分钟以获得可靠的解决方案(不依赖于Windows的区域设置),请继续阅读。

让我们释放思绪。你想简化脚本看起来像这样吗? (假设您要设置LOG_DATETIME变量)

12345FOR /F"tokens=* USEBACKQ" %%F IN (`FormatNow"yyyy-MM-dd"`) DO (   Set LOG_DATETIME=%%F ) echo I am going to write log to Testing_%LOG_DATETIME%.log

您可以。只需使用C#.NET构建FormatNow.exe并将其添加到PATH即可。

笔记:

您可以使用任何Visual Studio版本(如Visual Studio Express)来构建FormatNow.exe。 在Visual Studio中,选择"控制台应用程序"C#项目,而不是"Windows窗体应用程序"项目。 常识:构建的FormatNow.exe需要.NET Framework才能运行。 常识:将FormatNow.exe添加到PATH变量后,需要重启CMD才能生效。它也适用于环境变量的任何变化。

优点:

它不慢(在0.2秒内完成)。 支持多种格式https://msdn.microsoft.com/en-us/library/8kb3ddd4(v=vs.110).aspx 例如FormatNow"ddd"只获取星期几,FormatNow"yyyy"只获得一年 它不依赖于Windows的区域设置,因此其输出更可靠。另一方面,%date%不会在不同的计算机上提供一致的格式,并且不可靠。 您不需要创建这么多CMD变量并污染变量名称空间。 批处理脚本中需要3行来调用程序并获得结果。它应该足够短。

我使用Visual Studio 2010构建的FormatNow.exe的源代码(我更喜欢自己构建它以避免下载未知的,可能是恶意程序的风险)。只需复制并粘贴下面的代码,构建程序一次,然后您就拥有了一个可靠的日期格式化程序,以备将来使用。

1234567891011121314151617181920212223242526272829using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Globalization; namespace FormatNow {     class Program     {         static void Main(string[] args)         {             try             {                 if (args.Length < 1)                 {                     throw new ArgumentException("Missing format");                 }                 string format = args[0];                 Console.Write(DateTime.Now.ToString(format, CultureInfo.InvariantCulture.DateTimeFormat));             }             catch (Exception ex)             {                 Console.WriteLine(ex.ToString());             }         }     } }

通常,在处理复杂的逻辑时,我们可以通过构建一个非常小的程序并调用程序将输出捕获回批处理脚本变量来简化它。我们不是学生,我们没有参加考试,要求我们遵循批处理脚本专用规则来解决问题。在实际工作环境中,允许任何(合法)方法。为什么我们仍然要坚持Windows批处理脚本的不良功能,需要解决许多简单任务的变通方法?我们为什么要使用错误的工具来完成这项工作?



【本文地址】


今日新闻


推荐新闻


CopyRight 2018-2019 办公设备维修网 版权所有 豫ICP备15022753号-3